using DocumentCreationSystem.Services;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Win32;
using System;
using System.IO;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows;

namespace DocumentCreationSystem.Views
{
    public partial class PatchPreviewWindow : Window
    {
        private readonly ILogger<PatchPreviewWindow> _logger;
        private readonly AgentToolService _agentToolService;
        private string? _lastPreviewBase64;

        public PatchPreviewWindow(IServiceProvider serviceProvider)
        {
            InitializeComponent();
            _logger = serviceProvider.GetRequiredService<ILogger<PatchPreviewWindow>>();
            _agentToolService = serviceProvider.GetRequiredService<AgentToolService>();
        }

        private void ExpandAll_Click(object sender, RoutedEventArgs e)
        {
            if (DiffGroupsList?.ItemsSource is List<DiffGroup> groups)
            {
                foreach (var g in groups) g.IsExpanded = true;
                DiffGroupsList.ItemsSource = null;
                DiffGroupsList.ItemsSource = groups;
            }
        }

        private void CollapseAll_Click(object sender, RoutedEventArgs e)
        {
            if (DiffGroupsList?.ItemsSource is List<DiffGroup> groups)
            {
                foreach (var g in groups) g.IsExpanded = false;
                DiffGroupsList.ItemsSource = null;
                DiffGroupsList.ItemsSource = groups;
            }
        }

        private void ChooseTarget_Click(object sender, RoutedEventArgs e)
        {
            var ofd = new OpenFileDialog
            {
                Title = "选择需要生成补丁的目标文件",
                Filter = "Source Files (*.cs;*.md;*.txt;*.json;*.xml)|*.cs;*.md;*.txt;*.json;*.xml|All Files (*.*)|*.*"
            };
            if (ofd.ShowDialog() == true)
            {
                TargetFileText.Text = ofd.FileName;
            }
        }

        private void ChooseContent_Click(object sender, RoutedEventArgs e)
        {
            var ofd = new OpenFileDialog
            {
                Title = "选择包含新内容的文本文件(UTF-8)",
                Filter = "Text Files (*.txt;*.md;*.json;*.xml;*.cs)|*.txt;*.md;*.json;*.xml;*.cs|All Files (*.*)|*.*"
            };
            if (ofd.ShowDialog() == true)
            {
                NewContentPathText.Text = ofd.FileName;
            }
        }

        private async void GeneratePreview_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                var targetPath = TargetFileText.Text?.Trim();
                var contentPath = NewContentPathText.Text?.Trim();
                if (string.IsNullOrWhiteSpace(targetPath) || string.IsNullOrWhiteSpace(contentPath))
                {
                    StatusText.Text = "请先选择目标文件与新内容文件";
                    return;
                }
                var newContent = await File.ReadAllTextAsync(contentPath!);
                var base64 = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(newContent));

                var baseDir = System.IO.Path.GetDirectoryName(targetPath!);
                var projRoot = (Application.Current?.MainWindow as MainWindow)?.DocumentEditorControl?.CurrentProjectPath;
                var root = string.IsNullOrWhiteSpace(projRoot) ? Directory.GetCurrentDirectory() : projRoot!;
                var rel = targetPath!.StartsWith(root, StringComparison.OrdinalIgnoreCase) ? System.IO.Path.GetRelativePath(root!, targetPath!) : targetPath!;
                var diff = await _agentToolService.ExecuteToolAsync("create_patch", $"{rel}|{base64}");
                RenderDiffLines(diff);
                _lastPreviewBase64 = string.IsNullOrWhiteSpace(diff) || diff.Trim() == "(无变更)" ? null : Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(diff));
                StatusText.Text = _lastPreviewBase64 == null ? "(无变更)" : "预览已生成，可点击‘应用’";
            }
            catch (Exception ex)
            {
                StatusText.Text = $"生成预览失败: {ex.Message}";
            }
        }

        private async void Apply_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (string.IsNullOrEmpty(_lastPreviewBase64))
                {
                    StatusText.Text = "没有可应用的预览，请先生成预览";
                    return;
                }
                var result = await _agentToolService.ExecuteToolAsync("apply_patch_base64", _lastPreviewBase64);
                StatusText.Text = result;
            }
            catch (Exception ex)
            {
                StatusText.Text = $"应用补丁失败: {ex.Message}";
            }
        }

        private void Close_Click(object sender, RoutedEventArgs e) => Close();
    }

    // 解析diff，分组到文件，并标注行类型
    internal sealed class DiffGroup
    {
        public string Header { get; set; } = string.Empty; // 原始头文本
        public string DisplayFileName { get; set; } = string.Empty; // 供 UI 显示的文件名
        public string DisplayDir { get; set; } = string.Empty; // 供 UI 显示的相对目录
        public List<string> Breadcrumbs { get; set; } = new(); // 面包屑目录
        public bool IsExpanded { get; set; } = true;
        public int AddCount { get; set; }
        public int RemoveCount { get; set; }
        public int HunkCount { get; set; }
        public List<DiffItem> Lines { get; set; } = new();
    }

    internal sealed class DiffItem
    {
        public string LineText { get; set; } = string.Empty;
        public string Kind { get; set; } = "Context"; // Header/Hunk/Add/Remove/Context
        public string Sign { get; set; } = string.Empty; // 行首符号 + / - / @ / 空
        public string Content { get; set; } = string.Empty; // 去符号的正文
        public List<DiffToken> Tokens { get; set; } = new(); // 行内 token（用于简单高亮）
    }

    internal sealed class DiffToken
    {
        public string Text { get; set; } = string.Empty;
        public string BackgroundHex { get; set; } = "Transparent";
        public string ForegroundHex { get; set; } = "#111827"; // 默认深灰
    }

    partial class PatchPreviewWindow
    {
        // 为非增删行构建简单 tokens（保持当前策略一致）
        private static List<DiffToken> BuildSimpleTokens(string kind, string content)
        {
            if (kind == "Add" || kind == "Remove")
            {
                var list = new List<DiffToken>();
                var parts = content.Split(new[] { ' ', '\t' }, StringSplitOptions.None);
                foreach (var p in parts)
                {
                    if (string.IsNullOrEmpty(p)) { list.Add(new DiffToken { Text = " " }); continue; }
                    list.Add(new DiffToken { Text = p, BackgroundHex = kind == "Add" ? "#E6F4EA" : "#FDECEA", ForegroundHex = kind == "Add" ? "#0B6E0B" : "#B42318" });
                    list.Add(new DiffToken { Text = " " });
                }
                if (list.Count > 0 && list[^1].Text == " ") list.RemoveAt(list.Count - 1);
                return list;
            }
            return new List<DiffToken> { new DiffToken { Text = content } };
        }

        // 构建字符级中段高亮：计算公共前缀与后缀，中段视为变更高亮
        private static void BuildCharDiffTokens(string oldText, string newText, out List<DiffToken> oldTokens, out List<DiffToken> newTokens)
        {
            oldTokens = new List<DiffToken>();
            newTokens = new List<DiffToken>();

            oldText ??= string.Empty; newText ??= string.Empty;

            int prefix = 0;
            int maxPrefix = Math.Min(oldText.Length, newText.Length);
            while (prefix < maxPrefix && oldText[prefix] == newText[prefix]) prefix++;

            int suffix = 0;
            int maxSuffix = Math.Min(oldText.Length - prefix, newText.Length - prefix);
            while (suffix < maxSuffix && oldText[oldText.Length - 1 - suffix] == newText[newText.Length - 1 - suffix]) suffix++;

            var oldMidStart = prefix;
            var oldMidLen = Math.Max(0, oldText.Length - prefix - suffix);
            var newMidStart = prefix;
            var newMidLen = Math.Max(0, newText.Length - prefix - suffix);

            // old 前缀
            if (prefix > 0)
                oldTokens.Add(new DiffToken { Text = oldText.Substring(0, prefix) });
            // old 中段（删除/替换部分）
            if (oldMidLen > 0)
                oldTokens.Add(new DiffToken { Text = oldText.Substring(oldMidStart, oldMidLen), BackgroundHex = "#FDECEA", ForegroundHex = "#B42318" });
            // old 后缀
            if (suffix > 0)
                oldTokens.Add(new DiffToken { Text = oldText.Substring(oldText.Length - suffix) });

            // new 前缀
            if (prefix > 0)
                newTokens.Add(new DiffToken { Text = newText.Substring(0, prefix) });
            // new 中段（新增/替换部分）
            if (newMidLen > 0)
                newTokens.Add(new DiffToken { Text = newText.Substring(newMidStart, newMidLen), BackgroundHex = "#E6F4EA", ForegroundHex = "#0B6E0B" });
            // new 后缀
            if (suffix > 0)
                newTokens.Add(new DiffToken { Text = newText.Substring(newText.Length - suffix) });
        }

        private void RenderDiffLines(string diff)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(diff))
                {
                    DiffGroupsList.ItemsSource = null;
                    return;
                }

                var groups = new List<DiffGroup>();
                DiffGroup? current = null;

                var lines = diff.Replace("\r\n", "\n").Split('\n');
                foreach (var l in lines)
                {
                    var text = l;
                    if (string.IsNullOrEmpty(text)) text = string.Empty;

                    // 新文件头或文件行（统一diff一般以 ---/+++ 或者 diff --git 等形式出现）
                    if (text.StartsWith("+++ ") || text.StartsWith("--- ") || text.StartsWith("diff ") || text.StartsWith("Index: ") || text.StartsWith("*** "))
                    {
                        var header = text.Trim();
                        current = new DiffGroup { Header = header, IsExpanded = true };
                        // 尝试解析出展示用的文件名与目录
                        var name = header;
                        try
                        {
                            // 匹配 +++ b/xxx 或 --- a/xxx 或 diff --git a/xxx b/xxx
                            if (header.StartsWith("+++ ") || header.StartsWith("--- "))
                            {
                                var p = header.Substring(4).Trim();
                                name = p;
                            }
                            else if (header.StartsWith("diff "))
                            {
                                // 取最后一个路径作为文件名展示
                                var parts = header.Split(' ');
                                var last = parts[^1];
                                name = last;
                            }
                            var fileName = System.IO.Path.GetFileName(name);
                            var dir = name.Substring(0, Math.Max(0, name.Length - fileName.Length)).TrimEnd('/', '\\');
                            current.DisplayFileName = string.IsNullOrWhiteSpace(fileName) ? name : fileName;
                            current.DisplayDir = dir;
                            // 构造面包屑
                            var partsDir = dir.Replace("\\", "/").Trim('/');
                            current.Breadcrumbs = string.IsNullOrEmpty(partsDir) ? new List<string>() : new List<string>(partsDir.Split('/'));
                        }
                        catch { current.DisplayFileName = header; current.DisplayDir = string.Empty; current.Breadcrumbs = new List<string>(); }

                        groups.Add(current);
                        continue;
                    }

                    if (current == null)
                    {
                        current = new DiffGroup { Header = "(未识别文件)", IsExpanded = true };
                        groups.Add(current);
                    }

                    var kind = "Context";
                    var sign = string.Empty;
                    var content = text;

                    if (text.StartsWith("@@")) { kind = "Hunk"; sign = "@"; }
                    else if (text.StartsWith("+")) { kind = "Add"; sign = "+"; content = text.Length > 1 ? text.Substring(1) : string.Empty; }
                    else if (text.StartsWith("-")) { kind = "Remove"; sign = "-"; content = text.Length > 1 ? text.Substring(1) : string.Empty; }
                    else if (text.StartsWith("+++ ") || text.StartsWith("--- ")) { kind = "Header"; }

                    if (kind == "Add") current.AddCount++;
                    else if (kind == "Remove") current.RemoveCount++;
                    else if (kind == "Hunk") current.HunkCount++;

                    // 简单 token 化：Add/Remove 行按空白分词；与 Context/Hunk 统一为单 token
                    var tokens = new List<DiffToken>();
                    if (kind == "Add" || kind == "Remove")
                    {
                        var parts = content.Split(new[] { ' ', '\t' }, StringSplitOptions.None);
                        foreach (var p in parts)
                        {
                            if (string.IsNullOrEmpty(p)) { tokens.Add(new DiffToken { Text = " " }); continue; }
                            tokens.Add(new DiffToken { Text = p, BackgroundHex = kind == "Add" ? "#E6F4EA" : "#FDECEA", ForegroundHex = kind == "Add" ? "#0B6E0B" : "#B42318" });
                            tokens.Add(new DiffToken { Text = " " });
                        }
                        if (tokens.Count > 0 && tokens[^1].Text == " ") tokens.RemoveAt(tokens.Count - 1);
                    }
                    else
                    {
                        tokens.Add(new DiffToken { Text = content });
                    }

                    current.Lines.Add(new DiffItem { LineText = text, Kind = kind, Sign = sign, Content = content, Tokens = tokens });
                }

                // 二次处理：为删除/新增成对行进行字符级中段高亮
                foreach (var g in groups)
                {
                    var linesList = g.Lines;
                    for (int i = 0; i < linesList.Count; i++)
                    {
                        var cur = linesList[i];
                        if (cur.Kind == "Remove" && i + 1 < linesList.Count && linesList[i + 1].Kind == "Add")
                        {
                            var next = linesList[i + 1];
                            BuildCharDiffTokens(cur.Content, next.Content, out var tokensRemove, out var tokensAdd);
                            cur.Tokens = tokensRemove;
                            next.Tokens = tokensAdd;
                            i++; // 跳过已配对的新增行
                            continue;
                        }
                        if (cur.Tokens == null || cur.Tokens.Count == 0)
                        {
                            cur.Tokens = BuildSimpleTokens(cur.Kind, cur.Content);
                        }
                    }
                }

                DiffGroupsList.ItemsSource = groups;
            }
            catch { }
        }
    }


}
